﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Principal;

using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.AccessControl;
using Microsoft.SharePoint.Utilities;

namespace SPaDevToolkit.Administration
{
    public abstract class SPaWebServiceApplication : SPIisWebServiceApplication, ISPaWebServiceApplication
    {
        #region Constructors
        public SPaWebServiceApplication() { }

        public SPaWebServiceApplication(string name, SPIisWebService service, SPIisWebServiceApplicationPool applicationPool)
			: base(name, service, applicationPool)
        {
        }
        #endregion

        #region Overrides

        protected override void OnProcessIdentityChanged(SecurityIdentifier processSecurityIdentifier)
        {
            base.OnProcessIdentityChanged(processSecurityIdentifier);
            if (Databases != null)
            {
                foreach (var database in Databases)
                {
                    database.GrantDBOwnerAccess(processSecurityIdentifier);
                }
            }
        }

        #endregion

        public new bool CheckAdministrationAccess(SPCentralAdministrationRights rights)
        {
            return base.CheckAdministrationAccess(rights);
        }

        /// <summary>
        /// Gets the service instance.
        /// </summary>
        /// <typeparam name="SAP">The <see cref="T:SPIisWebServiceApplicationProxy"/> type</typeparam>
        /// <typeparam name="SP">The <see cref="T:SPIisWebServiceProxy"/> type</typeparam>
        /// <returns></returns>
        public static SAP GetServiceInstance<SAP, SP>()
            where SAP : SPIisWebServiceApplicationProxy
            where SP : SPIisWebServiceProxy
        {
            SP serviceProxy = SPFarm.Local.Services.GetValue<SP>();
            SAP proxy = null;

            foreach (SPServiceApplicationProxy applicationProxy in serviceProxy.ApplicationProxies)
            {
                SAP item = applicationProxy as SAP;

                if (item != null)
                {
                    proxy = item;
                    break;
                }
            }

            return proxy;
        }

        public static bool IsServiceApplicationNameValid<SA, S>(string sharedAppName, out string errorMessage)
            where SA : SPIisWebServiceApplication
            where S : SPIisWebService
        {
            if (string.IsNullOrEmpty(sharedAppName))
            {
                throw new ArgumentNullException("sharedAppName");
            }

            bool flag = true;
            errorMessage = string.Empty;
            char[] anyOf = new char[] { ',', ':', '=' };

            if (sharedAppName.IndexOfAny(anyOf, 0) >= 0)
            {
                flag = false;
                errorMessage = "Invalid Characters found.";
            }

            if (flag)
            {
                foreach (SA application in GetApplications<SA, S>())
                {
                    if (application.Name.Equals(sharedAppName, StringComparison.OrdinalIgnoreCase))
                    {
                        flag = false;
                        errorMessage = "Duplicate Service Application Found";
                        return flag;
                    }
                }
            }

            return flag;
        }

        public static List<SA> GetApplications<SA, S>()
            where SA : SPIisWebServiceApplication
            where S : SPIisWebService
        {
            S service = SPFarm.Local.Services.GetValue<S>();
            List<SA> list = new List<SA>();

            if (service != null)
            {
                foreach (SPServiceApplication application in service.Applications)
                {
                    SA item = application as SA;
                    if (item != null)
                    {
                        list.Add(item);
                    }
                }
            }

            return list;
        }

        public static SA GetApplicationById<SA, S>(Guid applicationId)
            where SA : SPIisWebServiceApplication
            where S : SPIisWebService
        {
            S service = SPFarm.Local.Services.GetValue<S>();

            if (service != null)
            {
                return service.Applications.GetValue<SA>(applicationId);
            }

            return null;
        }
        
        #region ISPaWebServiceApplication Members

        public virtual bool IsDatabaseNameInUse(string databaseName, string databaseServerName)
        {
            return false;
        }

        public virtual List<ISPaWebServiceApplicationDatabase> Databases
        {
            get { return null; }
        }
        #endregion
    }
}
